import traceback
from flask import Blueprint, current_app, request, jsonify
from flask_caching import Cache
import akshare as ak
import math
import pandas as pd
from app.models import db, User, Transaction, UserAsset, AssetTypeEnum, Preference, UserBehaviorStats
from datetime import datetime

fund_controller = Blueprint('fund_controller', __name__)
cache = Cache(config={'CACHE_TYPE':'simple'})

@fund_controller.before_app_request
def init_cache():
    cache.init_app(current_app)

@fund_controller.before_request
def log_request():
    current_app.logger.info(f"[FUND] {request.method} {request.url}")

@fund_controller.get('/list')
def get_info():
    """
    GET /fund/list
    返回开放式基金排行，字段包括：
    序号	int64	-
    基金代码	object	-
    基金简称	object	-
    日期	object	-
    单位净值	float64	-
    累计净值	float64	-
    日增长率	float64	注意单位: %
    近1周	float64	注意单位: %
    近1月	float64	注意单位: %
    近3月	float64	注意单位: %
    近6月	float64	注意单位: %
    近1年	float64	注意单位: %
    近2年	float64	注意单位: %
    近3年	float64	注意单位: %
    今年来	float64	注意单位: %
    成立来	float64	注意单位: %
    自定义	float64	注意单位: %
    手续费	object
    """
    cache_key = 'fund:list'
    data = cache.get(cache_key)
    if data:
        # current_app.logger.debug(f"[FUND] 从缓存中获取基金信息")
        return jsonify({'code': 0, 'data': data})

    try:
        # 拉取数据
        df = ak.fund_open_fund_rank_em(symbol="全部")
        df = df.rename(columns={
            '序号': 'index',
            '基金代码': 'code',
            '基金简称': 'name',
            '日期': 'date',
            '单位净值': 'unit_net_value',
            '累计净值': 'cumulative_net_value',
            '日增长率': 'daily_growth_rate',
            '近1周': 'weekly_growth_rate',
            '近1月': 'monthly_growth_rate',
            '近3月': 'quarterly_growth_rate',
            '近6月': 'semiannual_growth_rate',
            '近1年': 'annual_growth_rate_1y',
            '近2年': 'annual_growth_rate_2y',
            '近3年': 'annual_growth_rate_3y',
            '今年来': 'year_to_date_growth_rate',
            '成立来': 'since_inception_growth_rate',
            '自定义': 'custom_growth_rate',
            '手续费': 'fee'
            # 手续费列不需要
        })
        # 替换 NaT 为 None
        df = df.where(pd.notnull(df), None)
        # 打印实际拿到的列，确认结构
        # current_app.logger.debug(f"[FUND] raw columns = {df.columns.tolist()}")
        # current_app.logger.debug(f"[FUND] raw data = {df.head(5).to_dict(orient='records')}")
        # 直接转 records
        records = df.to_dict(orient='records')

        cache.set(cache_key, records, timeout=300)
        
        return jsonify({'code': 0, 'data': records})

    except Exception as e:
        # 打完整 traceback 到日志
        # current_app.logger.error("[FUND]基金信息records" + records)
        current_app.logger.error("[FUND] 获取基金信息失败：\n" + traceback.format_exc())
        # 并把异常消息返给前端
        return jsonify({'code': 500, 'msg': str(e)}), 500
    
@fund_controller.get('/trend')
def get_trend():
    """
    GET /bond/trend?symbol=1000228

    返回指定可转债的历史走势数据，字段包括
      date,
      单位净值,
      日增长率
      """
    symbol = request.args.get('symbol')
    if not symbol:
        return jsonify({'code': 1,'msg': '缺少 symbol 参数'}), 400

    cache_key = f'fund_trend_{symbol}'
    data=cache.get(cache_key)
    if data:
        current_app.logger.debug(f"[FUND] 从缓存中获取 {symbol} 走势数据")
        return jsonify({'code': 0, 'data': data})

    try:
        df = ak.fund_open_fund_info_em(symbol=symbol, indicator="单位净值走势")
        df = df.where(pd.notnull(df), None)  # 替换 NaN 为 None
        records = df.to_dict(orient='records')
        cache.set(cache_key, records, timeout=300)
        return jsonify({'code': 0, 'data': records})
    except Exception as e:
        current_app.logger.error(f"[FUND] 获取 {symbol} 走势数据失败: {e}")
        return jsonify({'code': 500, 'msg': str(e)}), 500    
    
@fund_controller.post('/buy')
def buy_stock():
    """
    POST /api/stock/buy
    购买基金
    请求参数：
    - userid: 用户ID
    - products_id: 基金代码
    - products_name: 基金名称
    - quantity: 购买数量
    - price: 当前价格
    -trade_time: 交易时间
    """
    try:
        data = request.json
        current_app.logger.debug(f"Request JSON: {data}")  # 打印请求的 JSON 数据
        userid = data.get('userid')
        if isinstance(userid, str):
            userid = int(userid)  # 如果 userid 是字符串，转换为整数

        products_id = data.get('products_id')
        products_name = data.get('products_name')
        quantity = data.get('quantity')
        price = data.get('price')

         

        if not all([userid, products_id, products_name, quantity, price]):
            return jsonify({'code': 1, 'msg': '缺少必要参数'}), 400

        # 设置交易时间为当前时间
        trade_time = datetime.now()
        # 计算交易金额
        trade_amount = quantity * price

        # 更新用户资产
        asset = UserAsset.query.filter_by(userid=userid, products_id=products_id).first()
        if asset:
            asset.quantity += quantity
        else:
            asset = UserAsset(
                userid=userid,
                products_id=products_id,
                products_name=products_name,
                type='基金',
                quantity=quantity,
                buy_price=price
            )
            db.session.add(asset)

        # 添加交易记录
        transaction = Transaction(
            userid=userid,
            products_id=products_id,
            products_name=products_name,
            type='基金',
            trade_type='买入',
            quantity=quantity,
            trade_time=trade_time,  # 使用当前时间
            trade_amount=trade_amount
        )
        db.session.add(transaction)
        ##
        behavior_stats = UserBehaviorStats.query.filter_by(user_id=userid).first()
        behavior_stats.total_transactions = UserBehaviorStats.total_transactions + 1
        behavior_stats.total_commission = UserBehaviorStats.total_commission + trade_amount
        ##
        db.session.commit()
        return jsonify({'code': 0, 'msg': '购买成功'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'msg': f'购买失败: {str(e)}'}), 500
    

@fund_controller.post('/sell')
def sell_stock():
    """
    POST /api/stock/sell
    卖出基金
    请求参数：
    - userid: 用户ID
    - products_id: 基金代码
    - products_name: 基金名称
    - quantity: 卖出数量
    - price: 当前价格
    """
    try:
        data = request.json
        userid = data.get('userid')
        products_id = data.get('products_id')
        products_name = data.get('products_name')
        quantity = data.get('quantity')
        price = data.get('price')

        if not all([userid, products_id, products_name, quantity, price]):
            return jsonify({'code': 1, 'msg': '缺少必要参数'}), 400

        trade_time = datetime.now()  # 设置交易时间为当前时间
        # 检查用户资产是否足够
        asset = UserAsset.query.filter_by(userid=userid, products_id=products_id).first()
        if not asset or asset.quantity < quantity:
            return jsonify({'code': 1, 'msg': '持仓不足，无法卖出'}), 400

        # 计算交易金额
        trade_amount = quantity * price

        # 更新用户资产
        asset.quantity -= quantity
        if asset.quantity == 0:
            db.session.delete(asset)

        # 添加交易记录
        transaction = Transaction(
            userid=userid,
            products_id=products_id,
            products_name=products_name,
            type='基金',
            trade_type='售出',
            quantity=quantity,
            trade_amount=trade_amount,
            trade_time=trade_time
        )
        db.session.add(transaction)
        ##
        behavior_stats = UserBehaviorStats.query.filter_by(user_id=userid).first()
        behavior_stats.total_transactions = UserBehaviorStats.total_transactions + 1
        behavior_stats.total_commission = UserBehaviorStats.total_commission + trade_amount
        ##
        db.session.commit()
        return jsonify({'code': 0, 'msg': '卖出成功'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'msg': f'卖出失败: {str(e)}'}), 500